console.log('---------------------装饰器Decorator--------------------')
console.log('---------------------类装饰器ClassDecorator--------------------')

// 不破坏类的结构，给类增加属性或者方法

// 定义一个类装饰器
const Base: ClassDecorator = (target) => {
  //   console.log('target:', target) //类的构造函数
  // 给类增加属性或者方法
  target.prototype.treeAge = 100
  target.prototype.getTree = () => {
    console.log('我是树')
  }
}
//写法一：
@Base
class Tree {
  treeName: string
  constructor(treeName: string) {
    this.treeName = treeName
  }
  getTreeName(): string {
    return this.treeName
  }
}
// 写法二：Base(Tree)  用来兼容不支持@Base语法的浏览器
// Base(Tree)
let tree = new Tree('大树') as any
console.log(tree.treeName, tree.treeAge, tree.getTreeName(), tree.getTree())

console.log(
  '---------------------类装饰器ClassDecorator--装饰器工厂（函数看柯里化）------------------'
)
// 装饰器工厂  用来传参  使用的是函数柯里化
const Base2 = (params: string) => {
  const fn: ClassDecorator = (target) => {
    target.prototype.tableName = params
  }
  return fn
}
@Base2('我是参数')
class Table {
  // ...
}
let table = new Table() as any
console.log('tableName:', table.tableName)

console.log(
  '---------------------方法装饰器MethodDecorator--装饰器工厂（函数看柯里化）----------------'
)
// 封装一个简单的GET请求
const Get = (url: string) => {
  const fn: MethodDecorator = (
    target: any,
    propertyKey,
    descriptor: PropertyDescriptor
  ) => {
    // console.log('target:', target)
    // console.log('propertyKey:', propertyKey)
    // console.log('descriptor:', descriptor)
    const xhr = new XMLHttpRequest()
    xhr.open('GET', url)
    xhr.onreadystatechange = () => {
      if (xhr.status == 200 && xhr.readyState == 4) {
        let result = JSON.parse(xhr.response).result
        target.list = result.list //也可以类中直接增加属性list并赋值
        descriptor.value(result)
      }
    }
    xhr.send(null)
  }
  return fn
}
const Name: PropertyDecorator = (target, propertyKey) => {
  console.log('------属性装饰器PropertyDecorator-----')
  console.log('target:', target)
  console.log('---propertyKey:', propertyKey)
}
interface Res {
  total: number
  list: any[]
}
class Http {
  @Name
  name: string
  constructor() {
    this.name = '奇奇'
  }
  @Get('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
  getList(data: Res) {
    console.log('获取到的数据：', data)
  }
}
let http = new Http() as any

const debounce = (delay: number) => {
  let timeout: any
  const fn = (
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) => {
    const value = descriptor.value
    descriptor.value = function (...args: any) {
      if (timeout) clearTimeout(timeout)
      timeout = setTimeout(() => {
        timeout = null
        value.apply(this, args)
      }, delay)
    }
    return descriptor
  }
  return fn
}

class Test {
  @debounce(500)
  static testDebounce(arg0: Date) {
    console.log('防抖:', Date)
  }
}

window.addEventListener('resize', () => {
  Test.testDebounce(new Date())
})
